<?php
declare (strict_types = 1);

namespace app\model;

use app\common\model\SchoolModel;
use app\common\service\redis\PoolRedis;
use think\facade\Log;
use think\Model;
use think\model\relation\BelongsTo;
use think\model\relation\HasMany;
use think\model\relation\HasOne;

/**
 * @mixin \think\Model
 */
class AdminStudentDormitory extends Model
{
    //池
    const NO_KEY = 'stu_dormitory_no:';

    const DOOR_TYPE_ARR = ['LQ'=>'乐奇(MAX 26)','KD'=>'阔道(MAX 16)','KD254'=>'阔道(MAX 127)','KP'=>'可普(MAX 32)'];

    public function getDoorTypeTextAttr($value,$data)
    {
        $type = self::DOOR_TYPE_ARR;
        return $data['door_type'] ? $type[$data['door_type']] : '';
    }

    public function school() {
        return $this->belongsTo(AdminSchool::class, 'school_id')
            ->where('is_delete', 0)->bind([
            'school_name' => 'name'
        ]);
    }

    public function dormitory(): BelongsTo {
        return $this->belongsTo(AdminDormitory::class, 'dormitory_id')
            ->where('is_delete', 0)
            ->bind([
            'dormitory_name' => 'name'
        ]);
    }

    public function icCard(): HasMany {
        return $this->hasMany('AdminStaffIcCard', 'student_dormitory_id', 'id')
            ->where('is_delete', 0);
    }

    public static function onAfterWrite($model)
    {
        // 软删除后处理
        if ($model->getAttr('is_delete') == 1) {
            self::removeKeys($model->getAttr('school_id'), $model->getAttr('id'));
            AdminStaffIcCard::update(['is_delete' => 1], ['student_dormitory_id' => $model->getAttr('id'), 'is_delete' => 0]);
        }
    }

    public static function onAfterInsert($adminStudentDormitory)
    {
        self::createNoList($adminStudentDormitory->school_id, $adminStudentDormitory->id, $adminStudentDormitory->door_type);
    }

    public static function onAfterDelete($adminStudentDormitory)
    {
        self::removeKeys($adminStudentDormitory->school_id, $adminStudentDormitory->id);
    }

    // 移除redis缓存
    public static function removeKeys($school_id,$student_dormitory_id)
    {
        $redis = PoolRedis::instance();
        $redis->del(self::NO_KEY.$school_id.":".$student_dormitory_id.":pool");
    }

    // 创建宿舍编号1-40,左进右出，职工和学生编号不保证连续
    // 阔道：0-31（只生成16个编号，一人占用2个）
    // 可普：0-31
    // 乐奇：0-25
    public static function createNoList($school_id,$student_dormitory_id,$door_type)
    {
        $redis = PoolRedis::instance();
        $len = self::getDoorTypeCardNumberLen($door_type);
        $key = self::NO_KEY.$school_id.":".$student_dormitory_id.":pool";
        for ($i = 0; $i < $len; $i++) {
            $redis->lPush($key, $i);
        }
        return true;
    }

    public static function getDoorTypeCardNumberLen($door_type) {
        $len = 32;
        if ($door_type) {
            if ($door_type == 'LQ'){
                $len = 26;
            }
            if ($door_type == 'KD'){
                $len = 16;
            }
            if ($door_type == 'KD254'){
                $len = 127;
            }
            if ($door_type == 'KP'){
                $len = 32;
            }
        }
        return $len;
    }

    // 阔道卡片最大数量-1 从0开始
    public static function getKDCardNumberMax($door_type) {
        $len = 32 - 1;
        if ($door_type == 'KD'){
            $len = 32 - 1;
        }
        if ($door_type == 'KD254'){
            $len = 254 - 1;
        }
        return $len;
    }

    // 动态分配宿舍编号 key => stu_dormitory_no:{school_id}:{student_dormitory_id} offset => staff_id
    public static function dynamicDistribution($staff, $student_dormitory_id, $door_type)
    {
        $redis = PoolRedis::instance();
        $len = self::getDoorTypeCardNumberLen($door_type);
        $distributionKey = self::NO_KEY."{$staff['school_id']}:{$student_dormitory_id}";
        $noKey = $distributionKey.':no';
        $no = $redis->hGet($noKey, $staff['id']);
        if ($no > 0) { // 0 默认的不要了
            if ($no >= $len) {
                // 超出最大编号，把这个编号删了，重新拿一个
                $redis->hSet($distributionKey.':del', $no, $staff['id']);
                $redis->hDel($noKey, $staff['id']);
            } else {
                return $no;
            }
        }
        $poolKey = $distributionKey.':pool';
        // 池不存在时自动创建
        if($redis->exists($noKey) == 0 && $redis->exists($poolKey) == 0) {
            AdminStudentDormitory::createNoList($staff['school_id'], $student_dormitory_id, $door_type);
        }
        $poolLen = $redis->lLen($poolKey);
        if ($poolLen > 0) { // 剩余编号大于0
            $no = (int)$redis->rPop($poolKey);
            for ($i = 1; $i < 20; $i++) {
                if ($no >= $len) {
                    $no = (int)$redis->rPop($poolKey);
                    continue;
                }
                break;
            }
            $redis->hSet($noKey, $staff['id'], $no);
            if ($staff['type'] > 0) {
                // 职工或教工编号
                $redis->zAdd($distributionKey.":score", time(), $staff['id']);
            }
            return $no;
        }
//        elseif ($redis->hLen($noKey) > 0 && $poolLen == 0 && $staff['type'] > 0) {
//            // 剩余编号不足，删除掉旧职工，编号提供给新职工
//            $sortArr = $redis->zRange($distributionKey.":score", 0, -1);
//            if ($sortArr) {
//                $del_val = current($sortArr);
//                $redis->zDelete($distributionKey.":score", $del_val);
//                $no = $redis->hGet($noKey, $del_val);
//                if ($no >- 1) {
//                    $redis->hDel($noKey, $del_val);
//                    // 保存被删除的职工编号和ID
//                    // $redis->hSet($distributionKey.':del', $no, $del_val);
//                    // 更新该编号为新职工
//                    $redis->hSet($noKey, $staff['id'], $no);
//                    $redis->zAdd($distributionKey.":score", time(), $staff['id']);
//                    return $no;
//                }
//            }
//        }
        return -1;
    }

    public static function resetPool($student_dormitory) {
        $redis = PoolRedis::instance();
        $len = AdminStudentDormitory::getDoorTypeCardNumberLen($student_dormitory->door_type);
        $distributionKey = AdminStudentDormitory::NO_KEY."{$student_dormitory->school_id}:{$student_dormitory->id}";
        $noKey = $distributionKey.':no';
        $poolKey = $distributionKey.':pool';
        // 超出长度的编号
        $noAll = $redis->hGetAll($noKey);
        foreach ($noAll as $index => $item) {
            if ($item >= $len){
                $redis->hDel($noKey, $index);
            }
        }
        // 重复的编号
        $noAll = $redis->hGetAll($noKey);
        foreach ($noAll as $index => $item) {
            foreach ($noAll as $index1 => $item1) {
                if ((int)$item1 == $item && $index1 != $index) {
                    unset($noAll[$index]);
                    $redis->hDel($noKey, $index1);
                    break;
                }
            }
        }
        // 重建编号池，已被使用的编号不添加
        $redis->del($poolKey);
        $noAll = $redis->hGetAll($noKey);
        for ($i = 1; $i < $len; $i++) {
            $esic = false;
            foreach ($noAll as $no) {
                if ((int)$no == $i) {
                    $esic = true;
                    break;
                }
            }
            if ($esic == false) {
                $redis->lPush($poolKey, $i);
            }
        }
    }

    public function getVoltageTimeAttr($value,$data)
    {
        return $data['voltage_time'] > 0 ? date('Y-m-d H:i:s', $data['voltage_time']) : '';
    }
}
